package com.sharp.portal.service;

import com.sharp.kernel.constant.CommonConst;
import com.sharp.kernel.mybatis.dao.entity.Columns;
import com.sharp.kernel.mybatis.dao.repository.ColumnsService;
import com.sharp.kernel.utils.ReflectionUtil;
import com.sharp.kernel.utils.StringUtil;
import com.sharp.kernel.vo.common.KeyValueResVO;
import com.sharp.portal.dao.entity.CoPortal;
import com.sharp.portal.dao.entity.CoPortalCondition;
import com.sharp.portal.dao.entity.CoPortalLayout;
import com.sharp.portal.dao.repository.CoPortalConditionService;
import com.sharp.portal.dao.repository.CoPortalLayoutService;
import com.sharp.portal.dao.repository.CoPortalService;
import com.sharp.portal.utils.PortalUtil;
import com.sharp.portal.vo.*;
import com.sharp.portal.vo.manage.ConditionUpdateVO;
import com.sharp.portal.vo.manage.FieldDisplayUpdateVO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Title: PortalLayoutService
 * Description: Copyright: Copyright (c) 2022 Company: Sharp Ltd.
 *
 * @author Sharp
 * @date 2022/09/27 13:40
 */
@Service
public class PortalManageService {

    @Value("${my.db.config.masterdb}")
    private String dbName;

    @Resource
    private CoPortalLayoutService coPortalLayoutRepository;
    @Resource
    private CoPortalService coPortalService;
    @Resource
    private CoPortalConditionService coPortalConditionService;
    @Resource
    private CoPortalLayoutService coPortalLayoutService;
    @Resource
    private ColumnsService columnsService;

    public LinkedHashMap<String, FieldDisplayVO> getFieldDisplayMap(String path) {
        List<CoPortalLayout> coPortalLayoutList = coPortalLayoutRepository.getPortalLayoutByPath(path);
        return PortalUtil.getFieldDisplayMap(coPortalLayoutList);
    }

    public ModelDisplayVO getModelDisplay(String uri) {
        CoPortal coPortal = coPortalService.selectByPrimaryKey(uri);
        ModelDisplayVO vo = ReflectionUtil.copy(coPortal, ModelDisplayVO.class);
        vo.setId(uri);
        vo.setName(coPortal.getDescription());
        vo.setValue(coPortal.getValue());
        CoPortalLayout pidField = coPortalLayoutRepository.getPortalLayoutPidField(coPortal.getPath());
        CoPortalLayout idField = coPortalLayoutRepository.getPortalLayoutIdField(coPortal.getPath());
        if (idField != null) {
            vo.setIdField(idField.getProperty());
        }
        if (pidField != null) {
            vo.setPidField(pidField.getPidField());
            vo.setTreeFormat(CommonConst.YES);
        }

        vo.setSqlDbName(coPortal.getSqlDbName());
        vo.setSqlTableName(coPortal.getSqlTableName());
        return vo;

    }

    public List<TreeDisplayVO> getTreeDisplay(String path, List<Map<String, String>> dataList) {
        CoPortalLayout pid = coPortalLayoutRepository.getPortalLayoutPidField(path);
        CoPortalLayout id = coPortalLayoutRepository.getPortalLayoutIdField(path);
        CoPortalLayout display = coPortalLayoutRepository.getPortalLayoutDisplayField(path);
        List<TreeItem> treeItemList = new ArrayList<>();
        try {
            if (CollectionUtils.isNotEmpty(dataList)) {
                for (Map<String, String> data : dataList) {
                    TreeItem vo = new TreeItem();
                    vo.setId(data.get(id.getProperty()));
                    vo.setPid(data.get(pid.getProperty()));
                    vo.setDisplayName(data.get(display.getProperty()));
                    treeItemList.add(vo);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return ReflectionUtil.buildTree(TreeDisplayVO.class, "subList", TreeItem.class, treeItemList, "id", "pid");
    }

    public List<KeyValueResVO> getAllPage() {
        List<KeyValueResVO> resList = new ArrayList<>();
        List<CoPortal> coPortals = coPortalService.selectValid();
        if (CollectionUtils.isNotEmpty(coPortals)) {
            for (CoPortal coPortal : coPortals) {
                KeyValueResVO keyValueResVO = new KeyValueResVO();
                keyValueResVO.setValue(coPortal.getPath());
                if (StringUtils.isNotBlank(coPortal.getDescription())) {
                    keyValueResVO.setLabel(coPortal.getDescription());
                } else {
                    keyValueResVO.setLabel(coPortal.getPath());
                }
                resList.add(keyValueResVO);
            }
        }
        return resList;
    }

    public int updateModelDisplay(ModelDisplayVO vo) {
        CoPortal coPortal = ReflectionUtil.copy(vo, CoPortal.class);
        coPortal.setPath(vo.getId());
        return coPortalService.updateByPrimaryKeySelective(coPortal);
    }

    @Transactional(rollbackFor = Exception.class)
    public int updateLayout(FieldDisplayUpdateVO vo) {
        int res = 0;
        List<CoPortalLayout> layout = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(vo.getLayoutList())) {
            coPortalLayoutRepository.deleteByPortalPath(vo.getPath());
            int displayOrder = 0;
            for (FieldDisplayVO fieldDisplayVO : vo.getLayoutList()) {
                CoPortalLayout coPortalLayout = ReflectionUtil.copy(fieldDisplayVO, CoPortalLayout.class);
                coPortalLayout.setPath(vo.getPath());
                coPortalLayout.setDisplayOrder(displayOrder++);
                layout.add(coPortalLayout);
            }
            res = coPortalLayoutRepository.insertBatch(layout);
        }
        return res;
    }

    public List<FieldDisplayVO> getLayout(String uri) {
        CoPortal coPortal = coPortalService.selectByPrimaryKey(uri);
        List<CoPortalLayout> coPortalLayoutList = coPortalLayoutRepository.getPortalLayoutByPath(coPortal.getPath());
        List<FieldDisplayVO> fieldDisplayVOList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(coPortalLayoutList)) {
            for (CoPortalLayout coPortalLayout : coPortalLayoutList) {
                FieldDisplayVO vo = ReflectionUtil.copy(coPortalLayout, FieldDisplayVO.class);
                fieldDisplayVOList.add(vo);
            }
        }
        return fieldDisplayVOList;
    }

    public List<ConditionVO> getCondition(String uri) {
        List<CoPortalCondition> coPortalConditionList = coPortalConditionService.getCondition(uri);
        List<ConditionVO> conditionVOList = new ArrayList<>();
        for (CoPortalCondition condition : coPortalConditionList) {
            ConditionVO vo = ReflectionUtil.copy(condition, ConditionVO.class);
            vo.setStatus(StringUtil.convertSwitch(condition.getStatus()));
            conditionVOList.add(vo);
        }
        return conditionVOList;
    }


    @Transactional(rollbackFor = Exception.class)
    public int updateCondition(ConditionUpdateVO req) {
        coPortalConditionService.deleteByPath(req.getPath());
        List<CoPortalCondition> coPortalConditionList = new ArrayList<>();
        for (ConditionVO vo : req.getConditionList()) {
            CoPortalCondition condition = ReflectionUtil.copy(vo, CoPortalCondition.class);
            condition.setPath(req.getPath());
            condition.setStatus(StringUtil.convertSwitch(vo.getStatus()));
            coPortalConditionList.add(condition);
        }
        return coPortalConditionService.insertBatch(coPortalConditionList);
    }


    public boolean existed(String path) {
        return coPortalService.selectByPrimaryKey(path) != null;
    }

    @Transactional(rollbackFor = Exception.class)
    public void refresh(String uri) {
        CoPortal coPortal = coPortalService.selectByPrimaryKey(uri);
        coPortalService.deleteByPrimaryKey(uri);
        coPortalLayoutService.deleteByPortalPath(uri);
        addQuery(uri, coPortal.getValue(), coPortal.getDescription(), coPortal.getSqlDbName(),
                coPortal.getSqlTableName());
    }


    @Transactional(rollbackFor = Exception.class)
    public void addQuery(String path, String value, String description, String dbName, String tableName) {
        CoPortal coPortal = coPortalService.createCoPortal(path, value, description, dbName, tableName);
        List<Columns> columns = columnsService.getColumns(dbName, tableName);
        List<CoPortalLayout> coPortalLayoutList = buildCoPortalLayoutList(coPortal, columns);
        coPortalLayoutService.insertBatch(coPortalLayoutList);
    }


    private List<CoPortalLayout> buildCoPortalLayoutList(CoPortal coPortal, List<Columns> columns) {
        List<CoPortalLayout> coPortalLayoutList = new ArrayList<>();
        String path = coPortal.getPath();
        int index = 0;
        for (Columns column : columns) {
            CoPortalLayout coPortalLayout = PortalUtil.buildCoPortalLayout(path, column);
            coPortalLayout.setDisplayOrder(index++);
            coPortalLayoutList.add(coPortalLayout);
        }
        return coPortalLayoutList;
    }
}
